
#include "KDTree.h"
#include "KDTreeLearner.h" 


#define	LEARN_DIFFERENCES	true		//param: indicates wheter we learn difference vectors or target states directly
#include "MREAgent.h"

KDTreeLearner::KDTreeLearner(MREAgent* m, int an, int od, taskspec_t& spec)
{
	m_agent = m; 
	action_number = an; 
	obs_dim = od; 


	learners = new KDTree* [an]; 
	for(int i=0; i< action_number; i++)
	{
		learners[i] = new KDTree [od]; 
		
		for(int j=0; j< od; j++)	//set the parameters of each learner(each output)
		{
/*			learners[i][j].setSplitCriterion(KDTree::SPLIT_USE_MAX_SAMPLES ); 
			learners[i][j].maxNumberOfSamples = 30; 
*/
			learners[i][j].dimension = od; 
			learners[i][j].ranges = spec.double_observations;  
			learners[i][j].knownMaxLength = 0.2;  //this is normalized
			learners[i][j].maxNumberOfSamples = 10; 
			learners[i][j].knownMinPoints = od+4; 
			learners[i][j].maxAllowedError = (spec.double_observations[j].max - spec.double_observations[j].min )/10; 
			learners[i][j].setDimensionParameters(spec.num_double_observations, spec.double_observations); 

//			learners[i][j].generalizerType = KDTree::GENERALIZER_USE_LINEAR ; 
//			learners[i][j].splitCriterion = KDTree::SPLIT_USE_MAX_ALLOWED_ERROR; 
			learners[i][j].generalizerType = KDTree::GENERALIZER_USE_MEAN ; 
			learners[i][j].splitCriterion = KDTree::SPLIT_USE_MAX_SAMPLES ; 
		}
	}

}


void KDTreeLearner::learn(const Transition* t) 
{

	Observation cdata = MREAgent::copyObservation(t->start); 
	dataPoints.push_back(cdata); 


	for(int i=0; i< obs_dim; i++)
	{
		learners[t->action][i].addPoint(dataPoints.back(), t->end[i] - t->start[i]); 
	}
}

double KDTreeLearner::getConfidence(Observation st, Action a)
{
	return getKnownness(st, a); 
}

double KDTreeLearner::getKnownness(Observation st, Action a)
{
	double min = 1; 
	for(int i=0; i < obs_dim; i++)
	{
		double tmp = learners[a][i].getKnownness(st); 
		if (tmp < min)
			min = tmp; 
	}

	return min; 
}

Observation KDTreeLearner::predict(Observation st, Action a)
{
	Observation result = new Observation_type[obs_dim]; 

	for(int i=0; i < obs_dim; i++)
	{
		if (! learners[a][i].predict(st, result[i]))	//unknown prediction
		{
			delete result; 
			return 0; 
		}

		if (LEARN_DIFFERENCES)
			result[i]+= st[i];  
	}
	return result; 
}

void KDTreeLearner::batchLearn( list<Transition>& history)
{
	/*
	printf("size of our list is: %d\n", dataPoints.size()); 
	for(list<Observation>::iterator it= dataPoints.begin(); it!= dataPoints.end(); it++)
		MREAgent::printObservation(*it); 

	exit(0); 
	*/

}







